package com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.web;

import java.util.List;
import java.util.Objects;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.github.pagehelper.PageInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.OuterDataSourceService;
import com.iwhalecloud.citybrain.flow.platform.manager.application.utils.StringUtils;
import com.iwhalecloud.citybrain.flow.platform.manager.common.ErrorCode;
import com.iwhalecloud.citybrain.flow.platform.manager.common.ResponseResult;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.FlowFormAppInfoVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.FlowFormExternalInfoDomain;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.form.*;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowFormRepository;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.common.exception.BusiException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

/**
 * @author cheng.huaxing
 * @date 2019-02-27
 */
@Api(value = "流程表单管理",tags = {"表单管理"})
@RestController
@RequestMapping("/form")
@Slf4j
public class FlowFormController {

    @Autowired
    private FlowFormRepository flowFormRepository;

    @Autowired
    private OuterDataSourceService dataSourceService;

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 获取外置表单信息
     * （司疆新增）
     */
    @ApiOperation(value = "获取外置表单信息")
    @PostMapping("/analyzeExternalFormInfo")
    public ResponseResult<FlowExternalFormInfoDTO> analyzeExternalFormInfo(@RequestBody FormAnalyzeDTO analyzeDTO){
        FlowExternalFormInfoDTO flowExternalFormInfoDTO;
        try{
            flowExternalFormInfoDTO =  flowFormRepository.analyzeExternalFormInfo(analyzeDTO);
        }catch (ResourceAccessException e){
            log.error("analyzeExternalFormInfo ResourceAccessException:",e);
            return ResponseResult.fail(ErrorCode.EXTERNAL_FORM_NOT_EXIST.errCode(),ErrorCode.EXTERNAL_FORM_NOT_EXIST.errMessage());
        }catch (RestClientException e){
            log.error("analyzeExternalFormInfo RestClientException:",e);
            return ResponseResult.fail(ErrorCode.EXTERNAL_FORM_RESOLVE_FAIL.errCode(),ErrorCode.EXTERNAL_FORM_RESOLVE_FAIL.errMessage());
        }
            return ResponseResult.success(flowExternalFormInfoDTO);
    }

    /**
     * 查看表单解析内容
     * @param analyzeDTO
     * @return
     */

    @ApiOperation(value = "查看表单解析内容")
    @PostMapping("/viewExternalFormInfo")
    public ResponseResult<ExternalFormDescriptionDTO> viewExternalFormInfo(@RequestBody FormAnalyzeDTO analyzeDTO){
        //通过url获取外置表单描述信息
        ExternalFormDescriptionDTO  descriptionDTO;
        try{
            descriptionDTO = restTemplate.getForObject(analyzeDTO.getFormDescriptionUrl(),ExternalFormDescriptionDTO.class);
        }catch (ResourceAccessException e){
            return ResponseResult.fail(ErrorCode.EXTERNAL_FORM_NOT_EXIST.errCode(),ErrorCode.EXTERNAL_FORM_NOT_EXIST.errMessage());
        }catch (RestClientException e){
            return ResponseResult.fail(ErrorCode.EXTERNAL_FORM_RESOLVE_FAIL.errCode(),ErrorCode.EXTERNAL_FORM_RESOLVE_FAIL.errMessage());
        }
        return ResponseResult.success(descriptionDTO);
    }


    @PostMapping("/isExternalForm")
    public ResponseResult<Boolean> isExternalForm (@RequestBody ExternalFormQueryDTO externalFormQueryDTO){
            return ResponseResult.success(flowFormRepository.isExternalForm(externalFormQueryDTO));
    }

    /**
     * 创建表单
     */
    @ApiOperation(value = "创建表单")
    @PostMapping("/create")
    public ResponseResult<String> create(@RequestBody @Validated FormCreateVO formCreateVo) {
        //目前表单没有跟应用关联，故先设置为0
        return ResponseResult.success(flowFormRepository.create(formCreateVo));
    }

    /**
     * 表单详情
     */
    @ApiOperation(value = "表单详情")
    @PostMapping("/detail")
    public ResponseResult<FormCreateVO> detail(@RequestBody FormQueryVO formQueryVO) {
        FormCreateVO formCreateVO = flowFormRepository.detail(formQueryVO.getFormId());
        if (Objects.isNull(formCreateVO)) {
            throw new BusiException(ErrorCode.FORM_NOT_EXIST);
        }
        return ResponseResult.success(formCreateVO);
    }

    /**
     * 获取外置表单详情
     * @param formKey
     * @return
     */
    @GetMapping("/externalDetail")
    public ResponseResult<ExternalFormDetailDTO> externalDetail(@RequestParam("formKey") String formKey){
        ExternalFormDetailDTO externalFormDetailDTO =  flowFormRepository.externalDetail(formKey);
        return ResponseResult.success(externalFormDetailDTO);

    }

    /**
     * 获取外置表单信息
     * @param taskId
     * @param processDefinitionKey
     * @return
     */

    //任务节点本身和任务无关，实例表单也可以挂在某一任务上开启
    @GetMapping("/externalFormInfo")
    public ResponseResult<FlowFormExternalInfoDomain> externalFormInfo(@RequestParam(required = false) String taskId, @RequestParam(required = false) String processDefinitionKey){
       String formKey ="";
        if(StringUtils.isNotEmpty(taskId)){
            formKey = flowFormRepository.resolveFormKeyFromTaskId(taskId);
            return ResponseResult.success(flowFormRepository.findRenderExternalFormInfo(formKey,taskId));
       }
       if(StringUtils.isNotEmpty(processDefinitionKey)){
           formKey = flowFormRepository.resolveFormKeyFromDefinitionKey(processDefinitionKey);
           return ResponseResult.success(flowFormRepository.findExternalFormInfo(formKey));
       }
       return ResponseResult.success();

    }

    /**
     * 获取外置表单用户数据
     * @param processInstanceId
     * @return
     */

    @ApiOperation(value = "获取外置启动表单明细")
    @GetMapping("/filledExternalFormInfo")
    public ResponseResult<ObjectNode> filledExternalFormInfo(@RequestParam(required = false) String processInstanceId, @RequestParam(required = false) String taskId) {

        return  ResponseResult.success(flowFormRepository.filledExternalFormInfo(processInstanceId,taskId));

    }
    @ApiOperation(value = "获取节点外置表单历史")
    @GetMapping("/historyExternalTaskForm")
    public ResponseResult<HistoryExternalTaskFormDTO> historyExternalTaskForm(@RequestParam  String taskId){
            return ResponseResult.success(flowFormRepository.historyExternalTaskForm(taskId));


    }
    @ApiOperation(value = "获取流程外置表单历史")
    @GetMapping("/historyExternalProcessForm")
    public ResponseResult<HistoryExternalProcessFormDTO> historyExternalProcessForm(@RequestParam String processInstanceId){
            return ResponseResult.success(flowFormRepository.historyExternalProcessForm(processInstanceId));
    }


    /**
     * 已部署表单详情
     */
    @ApiOperation(value = "已部署表单详情")
    @PostMapping("/deployment/detail")
    public ResponseResult<FormCreateVO> findDeployment(@RequestBody FormQueryVO formQueryVO) {
        FormCreateVO formCreateVO = flowFormRepository.findDeploymentById(formQueryVO.getFormDeployId());
        if (Objects.isNull(formCreateVO)) {
            throw new BusiException(ErrorCode.FORM_NOT_EXIST);
        }
        return ResponseResult.success(formCreateVO);
    }

    /**
     * 保存表单
     */
    @ApiOperation(value = "保存表单")
    @PostMapping("/save")
    public ResponseResult<Boolean> save(@RequestBody @Validated FormCreateVO formCreateVO) {
        return ResponseResult.success(flowFormRepository.save(formCreateVO));
    }

    /**
     * 删除表单 能力合并到【更新表单状态】接口，统一接口处理
     */
//    @ApiOperation(value = "删除表单")
    @PostMapping("/delete")
    public ResponseResult<Boolean> delete(@RequestBody @Validated FormQueryVO formQueryVO) {
        return ResponseResult.success(flowFormRepository.delete(formQueryVO.getFormId()));
    }
    /**
     * 更新表单状态
     */
    @ApiOperation(value = "更新表单状态")
    @PostMapping("/updateStatus")
    public ResponseResult<Boolean> updateStatus(@RequestBody @Validated FormQueryVO formQueryVO) {
        return ResponseResult.success(flowFormRepository.updateFormStatus(formQueryVO.getFormId(),formQueryVO.getStatus()));
    }
    /**
     * 删除部署表单
     */
    @ApiOperation(value = "删除部署表单")
    @PostMapping("/deployment/delete")
    public ResponseResult deploymentDelete(@RequestBody @Validated FormQueryVO formQueryVO) {
        Boolean delete = flowFormRepository.deploymentDelete(formQueryVO.getFormDeployId());
        if (Objects.isNull(delete)) {
            return ResponseResult.fail(ErrorCode.NOT_EXIST.errCode(), ErrorCode.NOT_EXIST.errMessage());
        }
        if (delete) {
            return ResponseResult.success();
        }
        return ResponseResult.fail(ErrorCode.PARAMETER_ERROR.errCode(), "删除失败");
    }

    /**
     * 表单列表
     *
     * @return
     */
    @ApiOperation(value = "表单列表")
    @PostMapping("/list")
    public ResponseResult<List<FlowFormAppInfoVo>> list(@RequestBody FormQueryVO formQueryVO) {
        PageInfo<FlowFormAppInfoVo> pageInfos = new PageInfo<>(flowFormRepository.list(formQueryVO));
        return ResponseResult.success(pageInfos.getList()).setTotalCount((int) pageInfos.getTotal())
                .setPageNum(pageInfos.getPageNum()).setPageSize(pageInfos.getPageSize());
    }


    /**
     * 复制表单
     */
    @ApiOperation(value = "复制表单")
    @PostMapping("/copy")
    public ResponseResult<String> copy(@RequestBody @Validated FormCopyVO formCopyVO) {
        return ResponseResult.success(flowFormRepository.copy(formCopyVO));
    }


    /**
     * 配置外部数据源时请求外部数据
     *
     * @param requestVo 请求信息
     * @return 数据
     */
    @ApiOperation(value = "配置外部数据源时请求外部数据")
    @PostMapping("/executeRequest")
    public Object executeRequest(@RequestBody @Validated({OuterSourceRequestVo.Config.class}) OuterSourceRequestVo requestVo) {
        return dataSourceService.execute(requestVo);
    }

    /**
     * 获取外部数据源信息
     *
     * @param requestVo 请求信息
     * @return 结果
     */
    @ApiOperation(value = "获取外部数据源信息")
    @PostMapping("/preRequestOuterData")
    public ResponseResult preRequest(@RequestBody @Validated({OuterSourceRequestVo.Pre.class}) OuterSourceRequestVo requestVo) {
        List<OptionItem> optionItems = dataSourceService.preRequestData(requestVo);
        JSONObject result = new JSONObject();
        result.put("list", optionItems);
        return ResponseResult.success(result);
    }

    @GetMapping("/formFieldList")
    public ResponseResult<List<FormFieldDTO>> getFormFieldList(@RequestParam("formId") String formId){
        List<FormFieldDTO> fieldList = flowFormRepository.getFormFieldDetail(formId);
        return ResponseResult.success(fieldList);
    }

}
